#include <avr/io.h>
#include <stdbool.h>		//for boolean
#include <stdio.h>			//i/o register definitions
#include <avr/interrupt.h>	//interrupt definitions
#include <stdint.h>			//for uint types
#include <stdlib.h>			//for rand
#include <stdbool.h>		//for boolean
#include "reciever.h"
#include "channelmonitor.h"

void initReceive()
{
	DDRD &= ~((1<<PD6) | (1<<PD3));//Sets the ICP1 to be an input
	receiveCount = 0;
	receiveLength = 0;
	receiveBufferCount = 0;
	first = true;
	display = false;
	
	TIMSK |= (1<<OCIE0);				//enable timer0 interrupt
	
	TCCR0 = (1<<WGM01); //CTC MODE
	OCR0 = 26; //104us, 1/4 bit interval
	receiving = false; //Not currently receiving
}

void displayBuffer()
{
	volatile int i = 0;
	for(i = 0; i < receiveBufferCount; ++i)
	{
		char c = (receiveBuffer[i]);
		if(i == 2){ // print the source address
			printf("s %u : ", c);
		}
		else if(i == 3){ // print the destination address
			printf("d %u : ", c);
		}
		else if(i > 6){ 		
			printf("%c", c); // print the message
		}		
	}
}

void handleReceiveCollision()
{
	TCCR0 &= ~((1<<CS01)|(1<<CS00)); // set first, disable timer
	first = true;
	receiveBufferCount = 0; //reset the buffer count
	receiveCount = 0;
}

ISR(TIMER0_COMP_vect){
	TCNT0 = 0;
	if(first){
		first = false;
		OCR0 = 104; // 416us next match
	}
	uint8_t data = PIND;
	data = (data>>PD6)&(0x01);
	receiveBuffer[receiveBufferCount] = (receiveBuffer[receiveBufferCount]<<1)|data;
	receiveCount++;
	//Receive stuff
	if(receiveCount >= 8)
	{
		
		receiveCount = 0;
		
		if(receiveBufferCount > 6){ // do not convert header bytes
			char c = (receiveBuffer[receiveBufferCount])&(0x7F); // if in data section, set upper bit to 0
			receiveBuffer[receiveBufferCount] = c;
		}		
		
		receiveBufferCount++;
		//display = true;
		if(receiveBufferCount == (receiveBuffer[4]+7)/*(c == '\n') || (c == '\r')*/)
		{
			TCCR0 &= ~((1<<CS01)|(1<<CS00)); // set first, disable timer
			first = true;
			receiving = false; //done
			displayBuffer();
			receiveBufferCount = 0; //reset the buffer count
		}
	}
}

/* INT1_vect
 * Purpose: 
 * Parameters:
 * Returns:
 */
ISR(INT1_vect)
{
	//Get the current INT1 level
	volatile bool currentMonitor = (PIND>>PD6)&0x01;
	//Check for an edge transition
//	if(currentMonitor != previousMonitor)
//	{
//		//Edge transition occurred, so set the current state
//		previousMonitor = currentMonitor;
		TCNT1 = 0; //Reset TCNT1 because edge transition occurred
		if(currentMonitor)
		{
			//Rising edge, so start the timer when receiving
			if(!transmitting)
			{
				
				if(first)
				{
					TCCR0 |= (1<<CS01)|(1<<CS00); // clk/64 start timer
					TCNT0 = 0;
					OCR0 = 26; // 104us, 1/4 bit interval
					receiving = true; //start
				}
			}
//		}
		//Current state is busy.  Idle and Collision states will be set in the timer
		// overflow
		busy = true;
		idle = false;
		collision = false;
	}
}